/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.woxthebox.draglistview.basecomponent;

import com.woxthebox.draglistview.minterface.MyObserver;
import com.woxthebox.draglistview.utils.FinalStaticBean;
import com.woxthebox.draglistview.utils.ToastUtil;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.ListContainer;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;

/**
 * 自定义相对布局，主要实现左右滑动的动画效果，以及手指按下抬起的点击效果
 *
 * @since 2021-04-19
 */
public class BaseDependentLayout extends DependentLayout implements
        Component.TouchEventListener, Component.LongClickedListener {
    private ShapeElement mGrayShapeElement = new ShapeElement();
    private ShapeElement mWhiteShapeElement = new ShapeElement();
    private Display display;
    private Component mLeftComponent;
    private Component mIncludeComponent;
    private Component mRightComponent;
    private MyObserver observer;
    private ListContainer listContainer;
    private float mTouchX;
    private float mTouchCenterX;
    private float mTouchY;
    private float mTouchCenterY;
    private boolean isSlide = false;
    private boolean isRed = false;
    private boolean isFirstAnimation = false;
    private boolean isLongClick = false;
    private boolean isEnable = true;
    private float oldContentY = 0;
    private float oldContentX = 0;

    /**
     * BaseDependentLayout的构造方法，在Java类中new时调用
     *
     * @param context
     */
    public BaseDependentLayout(Context context) {
        super(context);
        initShapeElement();
        init(context,null);
    }

    /**
     * BaseDependentLayout的构造方法，在xml布局中
     *
     * @param context
     * @param attrSet
     */
    public BaseDependentLayout(Context context, AttrSet attrSet) {
        super(context, attrSet);
        initShapeElement();
        init(context,attrSet);
    }

    /**
     * BaseDependentLayout的构造方法，在xml布局且加Style时调用
     *
     * @param context
     * @param attrSet
     * @param styleName
     */
    public BaseDependentLayout(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        initShapeElement();
        init(context,attrSet);
    }

    public void setEnable(boolean isEnable) {
        this.isEnable = isEnable;
    }

    public void setListContainer(ListContainer listContainer) {
        this.listContainer = listContainer;
    }

    public void setIsRed(boolean isB) {
        this.isRed = isB;
    }

    public void setSlide(boolean isB) {
        this.isSlide = isB;
    }

    private void init(Context context, AttrSet attrSet) {
        setTouchEventListener(this::onTouchEvent);
        setLongClickedListener(this::onLongClicked);
        display = DisplayManager.getInstance().getDefaultDisplay(context).get();
    }

    public void setObserver(MyObserver observer) {
        this.observer = observer;
    }

    /**
     * 设置左滑和右滑显示的布局以及包括item的父布局
     *
     * @param leftComponentId
     * @param rightComponentId
     * @param inCludeComponent
     */
    public void setComponents(int leftComponentId, int rightComponentId, int inCludeComponent) {
        mLeftComponent = findComponentById(leftComponentId);
        mRightComponent = findComponentById(rightComponentId);
        mIncludeComponent = findComponentById(inCludeComponent);
    }

    private void initShapeElement() {
        display = DisplayManager.getInstance().getDefaultDisplay(getContext()).get();
        mGrayShapeElement.setRgbColor(new RgbColor(FinalStaticBean.NUM_198,
                FinalStaticBean.NUM_198,
                FinalStaticBean.NUM_198));
        mWhiteShapeElement.setRgbColor(new RgbColor(FinalStaticBean.NUM_255,
                FinalStaticBean.NUM_255,
                FinalStaticBean.NUM_255));
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        int action = touchEvent.getAction();
        MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex());
        switch (action) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                touchDown(point);
                return true;
            case TouchEvent.POINT_MOVE:
                touchMove(point);
                break;
            case TouchEvent.PRIMARY_POINT_UP:
                touchUp(point);
                break;
            case TouchEvent.CANCEL:
                touchCancel();
                break;
            default:
                break;
        }
        return true;
    }

    private void touchDown(MmiPoint point) {
        mTouchX = point.getX();
        mTouchCenterX = point.getX();
        mTouchY = point.getY();
        mTouchCenterY = point.getY();
        oldContentX = getContentPositionX();
        oldContentY = getContentPositionY();
        if (!isRed) {
            setBackground(mGrayShapeElement);
            setAlpha(FinalStaticBean.NUM_HALF);
        }
    }

    private void touchCancel() {
        mTouchY = 0;
        mTouchX = 0;
        isLongClick = false;
        setContentPositionX(oldContentX);
        setContentPositionY(oldContentY);
        setBackground(mWhiteShapeElement);
        setAlpha(1);
        if (listContainer != null) {
            listContainer.setClickable(true);
        }
    }

    private void touchMove(MmiPoint point) {
        setBackground(mWhiteShapeElement);
        setAlpha(1);
        if (isSlide && !isRed && point.getX() > mTouchX
                && FinalStaticBean.NUM_150 > point.getY() - mTouchY) {
            if (mIncludeComponent != null && !isLongClick) {
                mRightComponent.setVisibility(Component.HIDE);
                mLeftComponent.setVisibility(Component.VISIBLE);
                mIncludeComponent.setContentPositionX(point.getX() - mTouchX);
                if (listContainer != null) {
                    listContainer.setEnabled(false);
                }
            }
        }

        if (isSlide && mIncludeComponent != null
                && mTouchX > point.getX()
                && FinalStaticBean.NUM_150 > point.getY() - mTouchY && !isLongClick) {
            if (isRed) {
                if (listContainer != null) {
                    listContainer.setEnabled(false);
                }
                float dis = display.getAttributes().width - (mTouchX - point.getX());
                mIncludeComponent.setContentPositionX(dis);
            } else {
                if (listContainer != null) {
                    listContainer.setEnabled(false);
                }
                mLeftComponent.setVisibility(Component.HIDE);
                mRightComponent.setVisibility(Component.VISIBLE);
                mIncludeComponent.setContentPositionX(display.getAttributes().width
                        - (mTouchX - point.getX()) - display.getAttributes().width);
            }
        }
    }

    private void touchUp(MmiPoint point) {
        isLongClick = false;
        setBackground(mWhiteShapeElement);
        setAlpha(1);
        if (mIncludeComponent != null && !isLongClick) {
            // 红色显现
            if (mIncludeComponent.getContentPositionX() > FinalStaticBean.NUM_150
                    && FinalStaticBean.NUM_150 < point.getX() - mTouchX) {
                leftComponentToRight();
            }
            if (mIncludeComponent.getContentPositionX() < display.getAttributes().width - FinalStaticBean.NUM_200
                    && mTouchX - point.getX() > FinalStaticBean.NUM_150
                    && FinalStaticBean.NUM_200 > point.getY() - mTouchY) {
                AnimatorProperty animatorProperty = mIncludeComponent.createAnimatorProperty();
                if (isRed) {
                    animatorProperty.moveFromX(mIncludeComponent.getContentPositionX())
                            .moveToX(0)
                            .setDuration(FinalStaticBean.NUM_1000)
                            .start();
                    isRed = false;
                } else {
                    rightCompoentToLeft(animatorProperty);
                }
            }
            if (mIncludeComponent.getContentPositionX() > 0
                    && mIncludeComponent.getContentPositionX() < FinalStaticBean.NUM_200) {
                rightComponentToLeft0();
            }
            if (mIncludeComponent.getContentPositionX() < 0
                    && mIncludeComponent.getContentPositionX() > -FinalStaticBean.NUM_200) {
                rightComponentToLeft(mIncludeComponent.createAnimatorProperty(),
                        mIncludeComponent.getContentPositionX(),
                        mRightComponent);
            }
        }
        if (listContainer != null) {
            listContainer.setEnabled(true);
        }
    }

    private void rightComponentToLeft(AnimatorProperty animatorProperty2,
                                      float contentPositionX,
                                      Component rightComponent) {
        animatorProperty2
                .moveFromX(contentPositionX)
                .moveToX(0)
                .setDuration(FinalStaticBean.NUM_1000)
                .setStateChangedListener(new Animator.StateChangedListener() {
                    @Override
                    public void onStart(Animator animator) {
                    }

                    @Override
                    public void onStop(Animator animator) {
                    }

                    @Override
                    public void onCancel(Animator animator) {
                    }

                    @Override
                    public void onEnd(Animator animator) {
                        rightComponent.setVisibility(Component.HIDE);
                    }

                    @Override
                    public void onPause(Animator animator) {
                    }

                    @Override
                    public void onResume(Animator animator) {
                    }
                }).start();
    }

    private void rightComponentToLeft0() {
        rightComponentToLeft(mIncludeComponent.createAnimatorProperty(),
                mIncludeComponent.getContentPositionX(),
                mLeftComponent);
    }

    /**
     * 删除Item
     *
     * @param animatorProperty
     */
    private void rightCompoentToLeft(AnimatorProperty animatorProperty) {
        animatorProperty.moveFromX(mIncludeComponent.getContentPositionX())
                .moveToX(-display.getAttributes().width)
                .setDuration(FinalStaticBean.NUM_1000)
                .setStateChangedListener(new Animator.StateChangedListener() {
                    @Override
                    public void onStart(Animator animator) {
                        isFirstAnimation = true;
                    }

                    @Override
                    public void onStop(Animator animator) {
                    }

                    @Override
                    public void onCancel(Animator animator) {
                    }

                    @Override
                    public void onEnd(Animator animator) {
                        if (isFirstAnimation) {
                            observer.response(BaseDependentLayout.this,FinalStaticBean.RIGHTMOVE);
                            isFirstAnimation = false;
                        }
                    }

                    @Override
                    public void onPause(Animator animator) {
                    }

                    @Override
                    public void onResume(Animator animator) {
                    }
                }).start();
    }

    private void leftComponentToRight() {
        AnimatorProperty animatorProperty = mIncludeComponent.createAnimatorProperty();
        animatorProperty.moveFromX(mIncludeComponent.getContentPositionX())
                .moveToX(display.getAttributes().width)
                .setDuration(FinalStaticBean.NUM_1000)
                .setStateChangedListener(new Animator.StateChangedListener() {
                    @Override
                    public void onStart(Animator animator) {
                        isFirstAnimation = true;
                        isRed = true;
                        HiLog.info(FinalStaticBean.DRAGLISTVIEW,"onStart");
                    }

                    @Override
                    public void onStop(Animator animator) {
                        HiLog.info(FinalStaticBean.DRAGLISTVIEW,"onStop");
                    }

                    @Override
                    public void onCancel(Animator animator) {
                        HiLog.info(FinalStaticBean.DRAGLISTVIEW,"onCancel");
                    }

                    @Override
                    public void onEnd(Animator animator) {
                        HiLog.info(FinalStaticBean.DRAGLISTVIEW,"onEnd");
                        if (isFirstAnimation) {
                            observer.response(BaseDependentLayout.this,FinalStaticBean.LEFTMOVE);
                            isFirstAnimation = false;
                        }
                    }

                    @Override
                    public void onPause(Animator animator) {
                        HiLog.info(FinalStaticBean.DRAGLISTVIEW,"onPause");
                    }

                    @Override
                    public void onResume(Animator animator) {
                        HiLog.info(FinalStaticBean.DRAGLISTVIEW,"onResume");
                    }
                }).start();
    }

    public void setStartElement(ShapeElement element) {
        mGrayShapeElement = element;
    }

    public void setEndElement(ShapeElement element) {
        mWhiteShapeElement = element;
    }

    /**
     * 二次滑动还原上一个
     */
    public void reset() {
        if (mIncludeComponent != null) {
            AnimatorProperty animatorProperty = mIncludeComponent.createAnimatorProperty();
            rightComponentToLeft(animatorProperty, display.getAttributes().width, mLeftComponent);
        }
    }

    /**
     * 将Item居中
     */
    public void itemToCenter() {
        float putX = mTouchCenterX + oldContentX - getEstimatedWidth() / FinalStaticBean.NUM_2;
        float putY = mTouchCenterY + oldContentY - getEstimatedHeight() / FinalStaticBean.NUM_2;
        if (isLongClick) {
            AnimatorProperty animatorProperty = createAnimatorProperty();
            if (!animatorProperty.isRunning()) {
                animatorProperty.moveToX(putX).moveToY(putY).start();
            }
        }
    }

    @Override
    public void onLongClicked(Component component) {
        isLongClick = true;
        if (isEnable) {
            itemToCenter();
        } else {
            ToastUtil.toast(getContext(), "Item long clicked");
        }
    }
}